#include "types.h"
#include "storage.h"
#include "file_system.h"
#include "string.h"
 
extern int RamDiskInit(void);
extern void memory_init(void);
extern void printk(char *fmt,...);
extern void *memory_malloc(unsigned int bytes);
extern void memory_free(void *p);
void vfs_print(void);
 
extern sd_t ramDisk;
 
// ----------------------------------------------
// vfs存储结构
// vfs文件系统头
// 文件:文件头,文件数据
#define VFS_FLAG "-vfsvfs-"
#define VFS_NAME_BYTES  8
// 文件系统头
typedef struct vfs_head
{
    // 文件系统名
    char name[VFS_NAME_BYTES];
    // 磁盘存储的文件数
    unsigned int fileNum;
}vfs_head_t;
 
#define VFS_FILE_NAME_BYTES 16
// 文件头
typedef struct vfs_file_head
{
    // 文件名
    char name[VFS_FILE_NAME_BYTES];
    // 文件字节数
    unsigned int bytes;
}vfs_file_head_t;
// ----------------------------------------------
 
fs_t vFS;
// LFS文件系统描述体在文件系统指针数组里的编号
#define VFS_NO  0
// LFS文件系统文件数量
static unsigned int vfsFileNum;
// LFS文件系统文件描述体指针
static file_t *pVFSInode;
 
static inline struct inode *VFSNameToInode(char *name)
{
    if (name == NULL)
    {
        return(NULL);
    }
    unsigned int i = 0;
    unsigned int n = 0;
    for (i = 0; i < vfsFileNum; i ++)
    {
        n = strlen(name);
        if (memncmp(name,pVFSInode[i].name,n) == SUC_RET)
        {
            return(&pVFSInode[i]);
        }
    }
    return(NULL);
}
 
static inline unsigned int VFSGetDataAddr(struct inode *pInode)
{
    if (pInode == NULL)
    {
        return(0);
    }
    return(pInode->offset + (vFS.pDevice)->vAddr);
}
 
// VFS文件系统初始化
int VFSInit(void)
{
    int ret = ERR_RET;
    unsigned int i = 0;
    unsigned int j = 0;
 
    // ramDisk盘初始化(VFS存放在ramDisk盘)
    ret = RamDiskInit();
    if (ret != SUC_RET)
    {
        printk("[VFSInit],RamDiskInit error\n");
        return(ERR_RET);
    }
    printk("RamDiskInit success\n");
 
    // 文件系统的文件依赖memory功能
    memory_init();
    printk("memory_init success\n");
 
    // 初始化vFS
    vFS.pDevice = &ramDisk;
    vFS.NameToInode = VFSNameToInode;
    vFS.GetDataAddr = VFSGetDataAddr;
    vFS.name = (char *)memory_malloc(VFS_NAME_BYTES + 1);
    if (vFS.name == NULL)
    {
        printk("[VFSInit],vFS.name memory_malloc error\n");
        return(ERR_RET);
    }
 
    ret = memnset(vFS.name,'\0',VFS_NAME_BYTES + 1);
    if (ret != SUC_RET)
    {
        printk("[VFSInit],vFS.name memnset error\n");
        memory_free(vFS.name);
        return(ERR_RET);
    }
 
    ret = memncpy("vfs",vFS.name,3);
    if (ret != SUC_RET)
    {
        printk("[VFSInit],vFS.name memncpy error\n");
        memory_free(vFS.name);
        return(ERR_RET);
    }
    // printk("vFS.name:%s\n",vFS.name);
    printk("init vFS success\n");
 
    // 判断磁盘里是否为vfs
    vfs_head_t *pVFSHead = (vfs_head_t *)((vFS.pDevice)->vAddr);
    // printk("(vFS.pDevice)->vAddr:%a\n",(vFS.pDevice)->vAddr);
    // printk("pVFSHead:%a\n",pVFSHead);
 
    ret = memncmp(pVFSHead->name,VFS_FLAG,VFS_NAME_BYTES);
    if (ret == ERR_RET)
    {
        printk("not vfs in disk\n");
        memory_free(vFS.name);
        return(ERR_RET);
    }
    printk("vfs in disk\n");
 
    vfsFileNum = pVFSHead->fileNum;
    printk("vfsFileNum:%a\n",vfsFileNum);
    
    if (vfsFileNum >= 1)
    {
        pVFSInode = (file_t *)memory_malloc(sizeof(file_t) * vfsFileNum);
        if (pVFSInode == NULL)
        {
            printk("memory_malloc error\n");
            memory_free(vFS.name);
            return(ERR_RET);
        }
        // printk("pVFSInode:%a\n",pVFSInode);
 
        vfs_file_head_t *pVFSFileHead = (vfs_file_head_t *)((char *)pVFSHead + sizeof(vfs_head_t));
        // printk("pVFSFileHead:%a\n",pVFSFileHead);
 
        for (i = 0; i < vfsFileNum; i ++)
        {
            // 设置inode属于的文件系统
            pVFSInode[i].pFs = &vFS;
 
            // 为inode的文件名分配空间
            pVFSInode[i].name = (char *)memory_malloc(VFS_FILE_NAME_BYTES + 1);
            if (pVFSInode[i].name == NULL)
            {
                printk("memory_malloc error,i:%a\n",i);
                // 释放已经分配的inode的名字内存
                for (j = 0; j < i; j ++)
                {
                    memory_free(pVFSInode[j].name);
                }
                memory_free(pVFSInode);
                pVFSInode = NULL;
                memory_free(vFS.name);
                vFS.name = NULL;
                return(ERR_RET);
            }
            printk("inode[%a] name malloc success\n",i);
 
            ret = memnset(pVFSInode[i].name,'\0',VFS_FILE_NAME_BYTES + 1);
            if (ret != SUC_RET)
            {
                printk("memnset error,i:%a\n",i);
                // 释放已经分配的inode的名字内存
                for (j = 0; j < i; j ++)
                {
                    memory_free(pVFSInode[j].name);
                }
                memory_free(pVFSInode);
                pVFSInode = NULL;
                memory_free(vFS.name);
                vFS.name = NULL;
                return(ERR_RET);
            }
            printk("inode[%a] name memnset success\n",i);
 
            // 获取文件名
            ret = memncpy(pVFSFileHead->name,pVFSInode[i].name,VFS_FILE_NAME_BYTES);
            if (ret != SUC_RET)
            {
                printk("memncpy error,i:%a\n",i);
                // 释放已经分配的inode的名字内存
                for (j = 0; j < i; j ++)
                {
                    memory_free(pVFSInode[j].name);
                }
                memory_free(pVFSInode);
                pVFSInode = NULL;
                memory_free(vFS.name);
                vFS.name = NULL;
                return(ERR_RET);
            }
            printk("inode[%a] name memncpy success\n",i);
            // printk("pVFSInode[%a].name:%s\n",i,pVFSInode[i].name);
 
            // printk("pVFSFileHead->bytes:%a\n",pVFSFileHead->bytes);
 
            pVFSInode[i].offset = (unsigned int)((char *)pVFSFileHead + sizeof(vfs_file_head_t) - (char *)pVFSHead);
            pVFSInode[i].size = pVFSFileHead->bytes;
            pVFSInode[i].flags = (unsigned int)0;
            
            pVFSFileHead = (vfs_file_head_t *)((char *)pVFSFileHead + sizeof(vfs_file_head_t) + (pVFSFileHead->bytes));
        }
    }
 
    // 注册LFS文件系统
    ret = FsRegister(&vFS,VFS_NO);
    if (ret != SUC_RET)
    {
        printk("FsRegister error\n");
        for(i = 0; i < vfsFileNum; i ++)
        {
            memory_free(pVFSInode[i].name);
            memory_free(&pVFSInode[i]);
        }
        memory_free(vFS.name);
    }
    printk("vfs registered\n");
 
    vfs_print();
    
    return(SUC_RET);
}
 
void vfs_print(void)
{
    unsigned int i = 0;
    for (i = 0; i < vfsFileNum; i ++)
    {
        printk("i:%a,name:%s,bytes:%a,offset:%a,addr:%a\n",i,pVFSInode[i].name,pVFSInode[i].size,pVFSInode[i].offset,vFS.GetDataAddr(&pVFSInode[i]));
    }
}
 
void vfs_test(void)
{
    int ret = ERR_RET;
    ret = VFSInit();
    if (ret != SUC_RET)
    {
        printk("VFSInit error\n");
        return;
    }
 
    vfs_print();
}